var Log = {
	elem: false,
	getElem: function() {
		return this.elem? this.elem : this.elem = $('log');
	},
	
	write: function(text) {
		var elem = this.getElem();
		elem.set('html', text);
		this.position();
	},
	
	position: function() {
		var canvas = $('infovis');
		var elem = this.getElem();
		elem.setStyles({
			'top':0,
			'left': canvas.getStyle("left").toInt() + canvas.getProperty("width")/2 - elem.offsetWidth / 2,
			'right':'auto'
		});
	}
};

var Layout = {

	init: function() {
		var size = Window.getSize();
		var header = $('header'), left = $('left'), infovisContainer = $('infovis');
		var headerOffset = header.getSize().y, leftOffset = left.getSize().x;

		var newStyles = {
			'height': Math.floor((size.y - headerOffset)),
			'width' : Math.floor((size.x - leftOffset))
		};

		infovisContainer.setProperties(newStyles);
		infovisContainer.setStyles(newStyles);
		infovisContainer.setStyles({
			'position':'absolute',
			'top': headerOffset + 'px',
			'left': leftOffset + 'px'
		});
		left.setStyle('height', newStyles.height);
		var totalHeight = 0;
		$$('.toggler').each(function(elem) {
			totalHeight += elem.offsetHeight;
		});
		var h = newStyles.height - totalHeight;
		$$('.content').each(function(elem) {
			elem.setStyle('height', h - 24);
		});
		$$('#navigation ul li a').each(function (elem) {
			elem.addEvent('click', function() {
				PageController.makeRequestAndPlot(elem.innerHTML.trim());
			});
		});
		this.initAccordion(h);
	},
	
	initAccordion: function(height) {
		new Accordion($$('.toggler'), $$('.element'), {
			display: 0,
			fixedHeight:height,
			onActive: function(toggler, element) {
				toggler.morph({
					'background-color': '#7389AE',
					'color':'#fff'	
				});
			},
			onBackground: function(toggler, element) {
				toggler.morph({
					'background-color': '#555',
					'color':'#d5d5d5'	
				});
			}
		});
	}
};

function init() {
  Config.nodeRadius = 3;
  var infovis = $('infovis');
  var w = infovis.offsetWidth, h = infovis.offsetHeight;
  //Create a new canvas instance.
  var canvas = new Canvas('mycanvas', {
    'injectInto':'infovis',
    'width': w,
    'height':h,
    'styles': {
        'fillStyle': '#ccddee',
        'strokeStyle': '#772277'
    },
    
    'backgroundCanvas': {
        'styles': {
            'fillStyle': '#444',
            'strokeStyle': '#444'
        },
        
        'impl': {
            'init': $empty,
            'plot': function(canvas, ctx) {
                var times = 6, d = Config.levelDistance;
                var pi2 = Math.PI*2;
                for(var i=1; i<=times; i++) {
                    ctx.beginPath();
                    ctx.arc(0, 0, i * d, 0, pi2, true);
                    ctx.stroke();
                    ctx.closePath();
                }
            }
        }
    }   
  });
  var rgraph= new RGraph(canvas,  {
  	clickedNodeId: "",
  	clickedNodeName: "",

  	onBeforeCompute: function(node) {
  		Log.write("centering " + node.name + "...");
  		if(this.clickedNodeName != "") History.add(this.clickedNodeName);
		this.clickedNodeId = node.id;
  		this.clickedNodeName = node.name;
		
  	},
  	
  	preprocessTree: function(json) {
  		var ch = json.children;
  		var getNode = function(nodeName) {
  			for(var i=0; i<ch.length; i++) {
  				if(ch[i].name == nodeName) return ch[i];
  			}
  			return false;
  		};
  		json.id = rgraph.root;
  		GraphUtil.eachAdjacency(rgraph.graph.getNode(rgraph.root), function(elem) {
  			var nodeTo = elem.nodeTo, jsonNode = getNode(nodeTo.name);
  			if(jsonNode) jsonNode.id = nodeTo.id;
  		});
  	},
  	
  	getDescription: function() {
  		var that = this;
  		Log.write("getting description...");
  		new Request({
  			'method':'get',
  			'url':'/description/' + encodeURIComponent(this.clickedNodeName) + '/',
  			onFailure: function() {
  				Log.write("Error getting description!");
  			},
  			
  			onSuccess: function(text) {
  				$('details').set('html', "<b>"+that.clickedNodeName + "</b><br /><br />" + text);
  				Log.write("done");
  			}
  		}).send();
  	},
  	
  	requestGraph: function() {
  		var that = this, id = this.clickedNodeId;
  		Log.write("requesting info <em>please wait...</em>");
  		var jsonRequest = new Request.JSON({
  			'url': '/dependencies/tree/' + encodeURIComponent(that.clickedNodeName) + '/',
  			onSuccess: function(json) {
  				Log.write("morphing...");
  				that.preprocessTree(json);
  				GraphOp.morph(rgraph, json, {
  					'id': id,
  					'type': 'fade',
  					'duration':2000,
  					hideLabels:true,
  					onComplete: function() {
  						that.getDescription();  						
  					},
  					
  					onAfterCompute: $empty,
  					onBeforeCompute: $empty
  				});
  			},
  			onFailure: function() {
  				Log.write("sorry, the request failed");
  			}
  		}).get();
  	},
  	
  //Add a controller to assign the node's name to the created label.	
  	onCreateLabel: function(domElement, node) {
  		var d = $(domElement);
  		d.setOpacity(0.6).set('html', node.name).addEvents({
  			'mouseenter': function() {
  				d.setOpacity(1);
  			},
  			
  			'mouseleave': function() {
  				d.setOpacity(0.6);
  			},
  			
  			'click': function() {
				var html = Log.elem.innerHTML.trim();
				if(html == "done" || html == "getting description...") rgraph.onClick(d.id);
  			}
  		});
  	},
  	
  	//Take off previous width and height styles and
  	//add half of the *actual* label width to the left position
  	// That will center your label (do the math man). 
  	onPlaceLabel: function(domElement, node) {
		domElement.style.display = "none";
		 if(node._depth <= 1) {
			domElement.innerHTML = node.name;
			domElement.style.display = "";
			var left = parseInt(domElement.style.left);
			domElement.style.width = '';
			domElement.style.height = '';
			var w = domElement.offsetWidth;
			domElement.style.left = (left - w /2) + 'px';
		} 
	},
	
	onAfterCompute: function() {
		Log.write("done");
		this.requestGraph();
	}
  });
  
  PageController.rgraph = rgraph;
}

var PageController = {
	rgraph: null,
	busy:false,
		
	makeRequestAndPlot: function(name) {
		if(this.busy) return;
		this.busy = true;
		var that = this;
		if(this.rgraph.busy == true) return;
		Animation.timer = clearInterval(Animation.timer);
		this.rgraph.busy = false;
		History.clear();
		name = encodeURIComponent(name);
		var rgraph = this.rgraph;
		rgraph.controller.clickedNodeId = "";
		rgraph.controller.clickedNodeName = "";
		Log.write("please wait... it might take a while");
		new Request.JSON({
		  	'url':'/dependencies/tree/'+ name +'/',
		  	onSuccess: function(json) {
				 GraphPlot.labelsHidden = false;
				 GraphPlot.labels = {};
				 $('mycanvas-label').empty().setStyle('display', '');				 
				  //load weighted graph.
				 rgraph.loadTreeFromJSON(json);
				  //compute positions
				  rgraph.compute();
				  //make first plot
				  rgraph.plot();
				  Log.write("done");
				  rgraph.controller.clickedNodeName = name;
				  that.busy = false;
				  that.requestForDetails(name);
		  	},
		  	
		  	onFailure: function() {
		  		Log.write("failed!");
		  	}
		}).get();
	},
	
	requestForDetails: function(name) {
		Log.write("getting description...");
		new Request({
			'method':'get',
			'url':'/description/' + encodeURIComponent(name) + '/',
			onFailure: function() {
				Log.write("Error getting description!");
			},
			
			onSuccess: function(text) {
				$('details').set('html', "<b>"+ name + "</b><br /><br />" + text);
				Log.write("done");
			}
		}).send();
	}
};

var History = {
	h: false,
	getHistory: function() {
		return this.h===false? this.h=$('previous-selected-nodes') : this.h;
	},
	
	clear: function() {
		this.getHistory().empty();
	},
	
	add: function(name) {
		var li = new Element('li');
		var a = new Element('a', {
			'events': {
				'click': function() {
					PageController.makeRequestAndPlot(name);
				}
			},
			'html': name,
			'href':'#'
		}).inject(li);
		li.inject(this.getHistory(), 'top');
	}
};


window.addEvent('domready', function() {
	Layout.init();
	init();
	PageController.makeRequestAndPlot('wine');
});
